package model

import (
	myConfig "common/config"
	"common/helper"
	myredis "common/redis"
	myUserHelp "common/userHelp"
	"database/sql"
	"errors"
	"fmt"
	g "github.com/doug-martin/goqu/v9"
	"github.com/go-redis/redis/v8"
	"github.com/speps/go-hashids"
	"github.com/valyala/fasthttp"
	rand2 "math/rand"
	"member/contrib/session"
	ryrpc "member/rpc"
	"strings"
	"time"
)

func MemberLogout(fctx *fasthttp.RequestCtx) {

	session.Destroy(fctx)
}

func GetUidFromToken(fctx *fasthttp.RequestCtx) string {
	value := fctx.UserValue("token")
	if value == nil {
		return ""
	}

	uid := string(value.([]byte))
	return uid
}

func MemberLogin(fctx *fasthttp.RequestCtx, prefix, vid, code, phone, email, password, ip, device, deviceNo string) (string, error) {

	//username := fmt.Sprintf("%s%s", phone, email)
	key := "merchant:ip_blacklist"
	if meta.MerchantRedis.SIsMember(ctx, key, ip).Val() {
		return "", errors.New(helper.IpBanErr)
	}

	// web/h5不检查设备号黑名单
	if device != "24" && device != "25" {

		// 检查设备号黑名单
		key = "merchant:device_blacklist"
		if meta.MerchantRedis.SIsMember(ctx, key, deviceNo).Val() {
			return "", errors.New(helper.DeviceBanErr)
		}
	}

	AccountName := phone
	if AccountName == "" {
		AccountName = email
	}

	if myUserHelp.IsTestAccount(AccountName) {
		prefix = ""
	}

	uid, ret := myUserHelp.GetMemberIdByAccountName(AccountName, prefix)
	if !ret {
		return "", errors.New(helper.UserNotExist)
	}

	uid, ret = myUserHelp.GetMemberIdByAccountNameAndPassword(AccountName, password, prefix)
	if !ret {
		return "", errors.New(helper.UsernameOrPasswordErr)
	}

	State := myUserHelp.GetMemberState(uid)
	if State == 2 {
		return "", errors.New(helper.Blocked)
	}

	if State == 3 {
		BlockTime := int64(myUserHelp.GetMemberBlockTime(uid))
		if (time.Now().Unix() - BlockTime) < int64(myConfig.GetGameCfgInt(myConfig.CfgBlockTimeLong))*60 {
			return "", errors.New(helper.Blocked)
		} else {
			myUserHelp.SetMemberState(uid, "1")
		}
	}
	//密码加密效验,上线时候放开
	//password = fmt.Sprintf("%d", MurmurHash(password,  myUserHelp.GetMemberCreateAt(uid)))
	//if password != myUserHelp.GetMemberLoginPsw(uid) {
	password = strings.ToLower(password)
	redisPassword := strings.ToLower(myUserHelp.GetMemberLoginPsw(uid))
	if password != redisPassword {
		//myUserHelp.AddMemberPswErrCnt(uid, 1)
		//PswErrCnt := myUserHelp.GetMemberPswErrCnt(uid)
		//if PswErrCnt >= myConfig.GetGameCfgInt(myConfig.CfgPswErrCntLimit) {
		//	if myConfig.GetGameCfgInt(myConfig.CfgBlockWay) == 0 {
		//		myUserHelp.SetMemberState(uid, "2")
		//	} else if myConfig.GetGameCfgInt(myConfig.CfgBlockWay) == 1 {
		//		if State == 1 {
		//			myUserHelp.SetMemberState(uid, "3")
		//			myUserHelp.SetMemberBlockTime(uid, time.Now().Unix())
		//		}
		//	}
		//}
		return "", errors.New(helper.PasswordErr)
	}

	myUserHelp.SetMemberPswErrCnt(uid, "0")
	if myUserHelp.GetMemberPid(uid) == "0" {
		myUserHelp.SetMemberPid(uid, helper.GenId())
	}
	var loginDevice string
	//玩家登录日志表
	switch device {
	case "24":
		loginDevice = "Web"
	case "25":
		loginDevice = "H5"
	case "35":
		loginDevice = "Android"
	case "36":
		loginDevice = "IOS"
	}
	loginLog := ryrpc.TblMemberLoginLog{
		Uid:       uid,
		Device:    loginDevice,
		LoginIp:   ip,
		LoginTime: time.Now().Format(time.DateTime),
	}

	query, _, _ := dialect.Insert("tbl_member_login_log").Rows(loginLog).ToSQL()
	myredis.AddLogToRedis(query)

	memberRecord := g.Record{
		"last_login_ip": ip,
		"last_login_at": time.Now().Unix(),
	}
	memberEx := g.Ex{
		"uid": uid,
	}
	query, _, _ = dialect.Update("tbl_member_base").Set(memberRecord).Where(memberEx).ToSQL()
	myredis.AddLogToRedis(query)

	myUserHelp.AddUserDailyAction(uid, myUserHelp.Action_Login)
	sid, err := session.Set([]byte(uid), uid)
	if err != nil {
		return "", errors.New(helper.SessionErr)
	}

	err = meta.MerchantRedis.Unlink(ctx, key).Err()
	if err != nil {
		return "", pushLog(err, helper.RedisErr)
	}

	myUserHelp.SetLastLoginIp(uid, ip)
	// 测试号登陆  重置金币
	if myUserHelp.GetMemberTester(uid) == 2 && len(uid) == 9 {
		SqlSelect := fmt.Sprintf("SELECT amount from tbl_member_test where uid=%s", uid)
		var LastBalance float64 = 0.0
		err := GetMasterDBInstance().Get(&LastBalance, SqlSelect)
		if err != nil {
			helper.SqlSelectErrLog("tbl_member_test:%s---%s", SqlSelect, err.Error())
		}
		myUserHelp.SetUserBalanceByFloat64(uid, LastBalance)
	}

	myUserHelp.GenInterest(uid)
	return sid, nil
}

func MemberVerify(id, code string) bool {

	code = fmt.Sprintf("cap:code:%s", code)
	id = fmt.Sprintf("cap:id:%s", id)
	cmd := meta.MerchantRedis.Get(ctx, id)
	val, err := cmd.Result()
	if err != nil || err == redis.Nil {
		helper.SqlSelectErrLog("redis:%s,\nerr:%s", cmd.String(), err)
		return false
	}

	code = strings.ToLower(code)
	if val != code {
		helper.SqlSelectErrLog("d:%s,\ncode:%s,\nval:%s", id, code, val)
		return false
	}

	_, _ = meta.MerchantRedis.Unlink(ctx, id).Result()

	return true
}
func GetRegHiddenControl(parentId string) (string, string, int, int) {
	var ChargeHiddenControlS string = ""
	var ChargeHiddenControlF string = ""
	var ChargeHiddenButtonS int = 2
	var ChargeHiddenButtonF int = 2

	var SysDisbindParentId string = parentId
	for i := 1; i <= 3; i++ {
		if SysDisbindParentId == "" || SysDisbindParentId == "0" {
			break
		}

		ChargeHiddenControlS = ""
		ChargeHiddenControlF = ""
		if i == 1 {
			SysDisbindParentId = parentId
			if myUserHelp.G_UserButton.GetSycChargeHiddenlv1(SysDisbindParentId) == 1 {
				ChargeHiddenControlS = myUserHelp.G_UserButton.GetChargeHiddenControlS(SysDisbindParentId)
				ChargeHiddenControlF = myUserHelp.G_UserButton.GetChargeHiddenControlF(SysDisbindParentId)

				ChargeHiddenButtonS = myUserHelp.G_UserButton.GetChargeHiddenSwitchS(SysDisbindParentId)
				ChargeHiddenButtonF = myUserHelp.G_UserButton.GetChargeHiddenSwitchF(SysDisbindParentId)
				break
			} else {
				if myUserHelp.G_UserButton.GetEnableSycChargeHiddenlv1(SysDisbindParentId) == 1 {
					break
				}
			}
		}

		if i == 2 {
			SysDisbindParentId = myUserHelp.GetProxyParentId(parentId)
			if myUserHelp.G_UserButton.GetSycChargeHiddenlv2(SysDisbindParentId) == 1 {
				ChargeHiddenControlS = myUserHelp.G_UserButton.GetChargeHiddenControlS(SysDisbindParentId)
				ChargeHiddenControlF = myUserHelp.G_UserButton.GetChargeHiddenControlF(SysDisbindParentId)

				ChargeHiddenButtonS = myUserHelp.G_UserButton.GetChargeHiddenSwitchS(SysDisbindParentId)
				ChargeHiddenButtonF = myUserHelp.G_UserButton.GetChargeHiddenSwitchF(SysDisbindParentId)
				break
			} else {
				if myUserHelp.G_UserButton.GetEnableSycChargeHiddenlv2(SysDisbindParentId) == 1 {
					break
				}
			}
		}

		if i == 3 {
			SysDisbindParentId = myUserHelp.GetProxyGrandId(parentId)
			if myUserHelp.G_UserButton.GetSycChargeHiddenlv3(SysDisbindParentId) == 1 {
				ChargeHiddenControlS = myUserHelp.G_UserButton.GetChargeHiddenControlS(SysDisbindParentId)
				ChargeHiddenControlF = myUserHelp.G_UserButton.GetChargeHiddenControlF(SysDisbindParentId)

				ChargeHiddenButtonS = myUserHelp.G_UserButton.GetChargeHiddenSwitchS(SysDisbindParentId)
				ChargeHiddenButtonF = myUserHelp.G_UserButton.GetChargeHiddenSwitchF(SysDisbindParentId)
				break
			} else {
				if myUserHelp.G_UserButton.GetEnableSycChargeHiddenlv3(SysDisbindParentId) == 1 {
					break
				}
			}
		}
	}

	return ChargeHiddenControlS, ChargeHiddenControlF, ChargeHiddenButtonS, ChargeHiddenButtonF
}
func CreateUserTable(uid string, BaseInsertSql string, BalanceInsertSql string,
	parentId string, unbindParentId string, operatorId string, regIP string, username string) error {
	var regSql []string

	regSql = append(regSql, BaseInsertSql)
	regSql = append(regSql, BalanceInsertSql)
	//周返还表
	tblWeekReturn := myUserHelp.TblMemberWeekReturn{
		Uid:              uid,
		DepositReturn:    0.00,
		BetReturn:        0.00,
		LostReturn:       0.00,
		ProxyCommiReturn: 0.00,
		Create_time:      time.Now().Format(time.DateTime),
	}

	sqltblWeekInsert, _, _ := dialect.Insert("tbl_member_return").Rows(&tblWeekReturn).ToSQL()
	regSql = append(regSql, sqltblWeekInsert)

	//玩家状态表
	tblStatus := myUserHelp.TblMemberStatus{
		Uid:                 uid,
		Deposit_bonus_stage: 0,
	}

	sqlStatusInsert, _, _ := dialect.Insert("tbl_member_status").Rows(&tblStatus).ToSQL()
	regSql = append(regSql, sqlStatusInsert)

	tblDisableArea := myUserHelp.TblMemberDisbindArea{
		Uid: uid,

		CfgType:          0,
		CfgInviteBase:    0,
		CfgInviteCount:   0,
		CfgDisbindCounts: 0,

		TotalInviteCounts:  0,
		TotalDisbindCounts: 0,

		MinInviteCounts:    0,
		MinDisbindCounts:   0,
		MinDisbindInterval: 0,
	}

	sqlDisableArea, _, _ := dialect.Insert("tbl_member_disbind_area").Rows(&tblDisableArea).ToSQL()
	regSql = append(regSql, sqlDisableArea)

	//玩家VIP
	tblMemberVip := myUserHelp.TblMemberVIP{
		Uid:            uid,
		Level:          0,
		WeekBonusTime:  time.Now().Unix(),
		MonthBonusTime: time.Now().Unix(),
		UpBonusLevel:   0,
	}

	sqltblMemberVip, _, _ := dialect.Insert("tbl_member_vip").Rows(&tblMemberVip).ToSQL()
	regSql = append(regSql, sqltblMemberVip)

	//玩家累计数据表
	tblAccu := myUserHelp.TblMemberAccu{
		Uid:            uid,
		Deposit:        0.00,
		DepositTimes:   0,
		Withdraw:       0.00,
		WithdrawTimes:  0,
		Running:        0.00,
		GameRound:      0,
		GameWinlost:    0.00,
		GameTax:        0.00,
		TurntableBonus: 0.00,
	}

	sqlAccuInsert, _, _ := dialect.Insert("tbl_member_accu").Rows(&tblAccu).ToSQL()
	regSql = append(regSql, sqlAccuInsert)

	//玩家累计数据表
	tblMemberLottery := myUserHelp.TblMemberLottery{
		Uid:            uid,
		Username:       username,
		LotteryDeposit: 0.00,
	}

	sqlMemberLottery, _, _ := dialect.Insert("tbl_member_lottery").Rows(&tblMemberLottery).ToSQL()
	regSql = append(regSql, sqlMemberLottery)

	var RtpControlWay int8 = 10
	var RtpControlValue int8 = 0

	var UserCommiButton int8 = 1
	var UserRechargeShareType int = 3
	var UserRechargeShareRate string = `[{"level":1,"rate":0},{"level":2,"rate":0},{"level":3,"rate":0}]`
	var UserRechargeShareRateF string = `[{"level":1,"rate":0},{"level":2,"rate":0},{"level":3,"rate":0}]`
	var UserRechargeButton int = 0
	var UserRechargeShareWagedReq int = 0

	var FakePPRtpControlValue int = 0
	var FakeJDBRtpControlValue int = 0
	var FakeJILIRtpControlValue int = 0
	if parentId != "" {
		ParentRtpControlWay := myUserHelp.G_UserButton.GetRtpControlWay(parentId)
		if ParentRtpControlWay >= 20 {
			RtpControlWay = int8(ParentRtpControlWay)
			RtpControlValue = int8(myUserHelp.G_UserButton.GetFakePGRtp(parentId))
			FakePPRtpControlValue = myUserHelp.G_UserButton.GetFakePPRtp(parentId)
			FakeJDBRtpControlValue = myUserHelp.G_UserButton.GetFakeJDBRtp(parentId)
			FakeJILIRtpControlValue = myUserHelp.G_UserButton.GetFakeJILIRtp(parentId)
		}

		//佣金开关是否同步下级
		CommiSwitchSyncSub := myUserHelp.G_UserButton.GetCommiSwitchSyncSub(parentId)
		if CommiSwitchSyncSub == 1 {
			//同步上级的佣金开关
			UserCommiButton = int8(myUserHelp.G_UserButton.GetCommiButton(parentId))
		}

		//充值分成是否同步下级
		RechargeShareSwitchSyncSub := myUserHelp.G_UserButton.GetRechargeShareSwitchSyncSub(parentId)
		if RechargeShareSwitchSyncSub == 1 {
			UserRechargeShareType = myUserHelp.G_UserButton.GetRechargeShareType(parentId)
			UserRechargeShareRate = myUserHelp.G_UserButton.GetRechargeShareRate(parentId)
			UserRechargeShareRateF = myUserHelp.G_UserButton.GetRRechargeShareRateF(parentId)
			UserRechargeButton = myUserHelp.G_UserButton.GetRechargeButton(parentId)
			UserRechargeShareWagedReq = myUserHelp.G_UserButton.GetRechargeShareWagedReq(parentId)
		}
	}

	//掉绑开关与掉绑配置处理
	var bindButton int8 = int8(myConfig.GetGameCfgInt(myConfig.CfgGlobalUnbindSwitch))
	if bindButton != 1 {
		bindButton = 2
	}

	var DisbindControl string = ""
	var SysDisbindParentId string = parentId
	for i := 1; i <= 3; i++ {
		if SysDisbindParentId == "" || SysDisbindParentId == "0" {
			break
		}

		DisbindControl = ""
		if i == 1 {
			SysDisbindParentId = parentId
			if myUserHelp.G_UserButton.GetSycDisbindlv1(SysDisbindParentId) == 1 {
				DisbindControl = myUserHelp.G_UserButton.GetDisbindControl(SysDisbindParentId)
				break
			} else {
				if myUserHelp.G_UserButton.GetEnableSycDisbindlv1(SysDisbindParentId) == 1 {
					break
				}
			}
		}

		if i == 2 {
			SysDisbindParentId = myUserHelp.GetProxyParentId(parentId)
			if myUserHelp.G_UserButton.GetSycDisbindlv2(SysDisbindParentId) == 1 {
				DisbindControl = myUserHelp.G_UserButton.GetDisbindControl(SysDisbindParentId)
				break
			} else {
				if myUserHelp.G_UserButton.GetEnableSycDisbindlv2(SysDisbindParentId) == 1 {
					break
				}
			}
		}

		if i == 3 {
			SysDisbindParentId = myUserHelp.GetProxyGrandId(parentId)
			if myUserHelp.G_UserButton.GetSycDisbindlv3(SysDisbindParentId) == 1 {
				DisbindControl = myUserHelp.G_UserButton.GetDisbindControl(SysDisbindParentId)
				break
			} else {
				if myUserHelp.G_UserButton.GetEnableSycDisbindlv3(SysDisbindParentId) == 1 {
					break
				}
			}
		}
	}

	ChargeHiddenControlS, ChargeHiddenControlF, ChargeHiddenButtonS, ChargeHiddenButtonF := GetRegHiddenControl(parentId)

	var ChargeHiddenButton int = 2

	if ChargeHiddenControlS != "" || ChargeHiddenControlF != "" {
		ChargeHiddenButton = 1
	}

	var isBlogger int8 = 2
	if (parentId == "" || parentId == "0") && (unbindParentId == "0" || unbindParentId == "") &&
		operatorId != myConfig.Def_Channel {
		isBlogger = 1
	}

	tblMemCtrl := myUserHelp.MemberControllerButton{
		Uid:                        uid,
		GameButton:                 1,
		WithdrawButton:             1,
		TaxButton:                  1,
		AutoWithdrawButton:         1,
		ControlCodeButton:          1,
		UnbindButton:               bindButton,
		DisbindControl:             DisbindControl,
		IsBloger:                   isBlogger,
		WinFlowMultiple:            1.00,
		LoseFlowMultiple:           1.00,
		FakePgButton:               1,
		CommiButton:                UserCommiButton,
		RtpcontrolWay:              RtpControlWay,
		Rtp:                        RtpControlValue,
		RechargeShareType:          UserRechargeShareType,
		RechargeButton:             UserRechargeButton,
		RechargeShareWagedReq:      UserRechargeShareWagedReq,
		CommiSwitchSyncSub:         0,
		RechargeShareSwitchSyncSub: 0,
		RechargeShareRate:          UserRechargeShareRate,
		RechargeShareRateF:         UserRechargeShareRateF,
		SandbagAmountMax:           0.00,
		SandbagSwitch:              0,
		RechargeHiddenSwitch:       2,
		SycDisbindlv1:              "0,0",
		SycDisbindlv2:              "0,0",
		SycDisbindlv3:              "0,0",
		Fake_pp_rtp:                FakePPRtpControlValue,
		Fake_JDB_rtp:               FakeJDBRtpControlValue,
		Fake_JILI_rtp:              FakeJILIRtpControlValue,
		SycChargeHiddenlv1:         "0,0",
		SycChargeHiddenlv2:         "0,0",
		SycChargeHiddenlv3:         "0,0",
		ChargeHiddenControlS:       ChargeHiddenControlS,
		ChargeHiddenControlF:       ChargeHiddenControlF,
		ChargeHiddenButtonS:        ChargeHiddenButtonS,
		ChargeHiddenButtonF:        ChargeHiddenButtonF,
		ChargeHiddenButton:         ChargeHiddenButton,
	}

	sqlMemCtrlInsert, _, _ := dialect.Insert("tbl_member_controller_button").Rows(&tblMemCtrl).ToSQL()
	regSql = append(regSql, sqlMemCtrlInsert)
	//代理基础表
	if parentId == "" {
		parentId = "0"
	}

	var lv1ParentId string = "0"
	var lv2ParentId string = "0"
	var lv3ParentId string = "0"

	var lv1ParentName string = ""
	var lv2ParentName string = ""
	var lv3ParentName string = ""

	lv1ParentId = parentId
	if parentId != "0" {
		lv1ParentName = myUserHelp.GetMemberName(lv1ParentId)

		lv2ParentId = myUserHelp.GetProxyParentId(parentId)
		if lv2ParentId != "0" {
			lv2ParentName = myUserHelp.GetMemberName(lv2ParentId)
		}
		lv3ParentId = myUserHelp.GetProxyGrandId(parentId)
		if lv3ParentId != "0" {
			lv3ParentName = myUserHelp.GetMemberName(lv3ParentId)
		}
	}

	tblProxyBase := myUserHelp.TblProxyBase{
		Uid:               uid,
		ParentID:          lv1ParentId,
		ParentName:        lv1ParentName,
		GrandId:           lv2ParentId,
		GrandName:         lv2ParentName,
		GreatGrandId:      lv3ParentId,
		GreatGrandName:    lv3ParentName,
		DonateToParent:    0.00,
		FirstDepositMount: 0.00,
		CreatedTime:       time.Now().Format(time.DateTime),
		DonateTime:        time.Now().Format(time.DateTime),
		UnbindParentId:    unbindParentId,
		RegIP:             regIP,
	}

	sqlProxyBaseInsert, _, _ := dialect.Insert("tbl_proxy_base").Rows(&tblProxyBase).ToSQL()
	regSql = append(regSql, sqlProxyBaseInsert)

	//储蓄罐 表
	tblPiggyBank := myUserHelp.TblPiggyBank{
		Uid:              uid,
		PiggyAmount:      0.00,
		Interest:         0.00,
		TotalInterest:    0.00,
		InterestCalcTime: time.Now().Unix(),
		InterestEndTime:  time.Now().Unix(),
	}
	sqlPiggyBankInsert, _, _ := dialect.Insert("tbl_member_piggy_bank").Rows(&tblPiggyBank).ToSQL()
	regSql = append(regSql, sqlPiggyBankInsert)

	//储蓄罐 表
	tblMemberInfo := myUserHelp.TblMemberInfo{
		Uid:               uid,
		EnableLuckyPoint:  0.00,
		ExpiredLuckyPoint: 0.00,
		UsedLuckyPoint:    0.00,
	}
	SqlMemberInfo, _, _ := dialect.Insert("tbl_member_info").Rows(&tblMemberInfo).ToSQL()
	regSql = append(regSql, SqlMemberInfo)

	sqlProxyAccu := fmt.Sprintf("insert into tbl_proxy_accu(uid,level,created_at)VALUES(%s,1,'%s')", uid, time.Now().Format(time.DateTime))
	regSql = append(regSql, sqlProxyAccu)
	sqlProxyAccu = fmt.Sprintf("insert into tbl_proxy_accu(uid,level,created_at)VALUES(%s,2,'%s')", uid, time.Now().Format(time.DateTime))
	regSql = append(regSql, sqlProxyAccu)
	sqlProxyAccu = fmt.Sprintf("insert into tbl_proxy_accu(uid,level,created_at)VALUES(%s,3,'%s')", uid, time.Now().Format(time.DateTime))
	regSql = append(regSql, sqlProxyAccu)
	tx, err := meta.MerchantDB.Begin() // 开启事务
	if err != nil {
		return err
	}

	for _, value := range regSql {
		_, err = tx.Exec(value)
		if err != nil {
			tx.Rollback()
			helper.SqlErrLog("Register Sql:%s:reason:%s", value, err.Error())
			return pushLog(err, helper.DBErr)
		}
	}

	err = tx.Commit()
	if err != nil {
		helper.SqlErrLog("reason:%s", err.Error())
		return pushLog(err, helper.DBErr)
	}

	myUserHelp.LoadUserToRedis(uid)
	//插入成功 往blog_list表中插入数据(如果是
	if isBlogger == 1 {
		username := myUserHelp.GetMemberName(uid)
		sqlBloggerlst := fmt.Sprintf("insert into tbl_bloger_list(uid,bloger_name,bloger_date) "+
			"values (%s,'%s',%d)",
			uid, username, time.Now().Unix())
		_, errExec := meta.MerchantDB.Exec(sqlBloggerlst)
		if errExec != nil {
			helper.SqlErrLog("blogger_list:%s---%s", sqlBloggerlst, errExec.Error())
		}
	}

	return nil
}

/*
businessId 	业务员id
channelId 	渠道id
linkID 		上级id
三者只会存在一个
*/
func MemberReg(device int, prefix, captchaId, email, password, ip, deviceNo, regUrl, linkID, phone, ts, businessId, channelId string, createdAt uint32, extendParams map[string]interface{}) (string, error) {

	username := extendParams["Username"].(string)
	// 检查ip黑名单
	username = strings.ToLower(username)
	dataFieldLock := fmt.Sprintf("%s", username)
	if !myredis.Lock(GetRedisInstance(), dataFieldLock) {
		return "", errors.New(helper.RequestBusy)
	}

	defer myredis.Unlock(GetRedisInstance(), dataFieldLock)

	if meta.MerchantRedis.SIsMember(ctx, "merchant:ip_blacklist", ip).Val() {
		return "", errors.New(helper.IpBanErr)
	}

	if username != "" {
		usernamePrefix := username + prefix
		if meta.MerchantRedis.SIsMember(ctx, "usernameExist", usernamePrefix).Val() {
			helper.InfoLog("11111111111111:%s", usernamePrefix)
			return "", errors.New(helper.UsernameExist)
		}
	}

	/*
		if email != "" {
			if meta.MerchantRedis.SIsMember(ctx, "emailExist", email).Val() {
				return "", errors.New(helper.EmailExist)
			}
		}
	*/

	CfgRegIpLimit := myConfig.GetGameCfgInt(myConfig.CfgRegIpLimit)
	var RegIpCount int
	SqlSelect := fmt.Sprintf("SELECT COUNT(*) FROM tbl_member_base WHERE created_ip='%s'", ip)
	meta.MerchantDB.Get(&RegIpCount, SqlSelect)

	if RegIpCount >= CfgRegIpLimit {
		helper.InfoLog("SQL:%s,result:%d", SqlSelect, RegIpCount)
		return "", errors.New(helper.RegIpMax)
	}

	//if !helper.CtypeDigit(ts) {
	//	return "", errors.New(helper.ParamErr)
	//}

	// web/h5不检查设备号黑名单
	if _, ok := WebDevices[device]; !ok {

		// 检查设备号黑名单
		key1 := "merchant:device_blacklist"
		if meta.MerchantRedis.SIsMember(ctx, key1, deviceNo).Val() {
			return "", errors.New(helper.DeviceBanErr)
		}
	}

	//if MemberExist(username) {
	//	return "", errors.New(helper.UsernameExist)
	//}

	/*
		ex := g.Ex{}
		if phone != "" {
			ex["phone"] = phone
			if MemberBindCheck(ex) {
				return "", errors.New(helper.PhoneExist)
			}
		}
	*/

	ex := g.Ex{}
	if username != "" {
		ex["username"] = username
		ex["prefix"] = prefix
		if MemberBindCheck(ex) {
			helper.InfoLog("222222222222")
			return "", errors.New(helper.UsernameExist)
		}
	}

	/*
		if email != "" {
			ex["email"] = email
			if MemberBindCheck(ex) {
				return "", errors.New(helper.EmailExist)
			}
		}
	*/

	//生成唯一ID
	rand2.New(rand2.NewSource(time.Now().UnixNano()))
	sid := rand2.Intn(89999999)
	sid += 10000000

	for {
		userId := fmt.Sprintf("%d", sid)
		if meta.MerchantRedis.SIsMember(ctx, "RegUserId", userId).Val() {
			rand2.New(rand2.NewSource(time.Now().UnixNano()))
			sid = rand2.Intn(89999999)
			sid += 10000000
		} else {
			meta.MerchantRedis.SAdd(ctx, "RegUserId", userId)
			break
		}
	}

	var err error
	operatorId := myConfig.Def_Channel

	if businessId == "" {
		businessId = "0"
	}

	if businessId != "0" {
		cfgOperatorId, isFind := myConfig.FindOperatorIdByBussinessId(businessId)
		if isFind {
			operatorId = cfgOperatorId
		} else {
			businessId = "0"
		}
	} else if channelId != "" {
		isFind := myConfig.IsExistOperatorId(channelId)
		if isFind {
			operatorId = channelId
		}
	} else {
		businessId = "0"
	}

	uid := fmt.Sprintf("%d", sid)
	//var parent myUserHelp.TblMemberBase

	var unbindParentId = "0"
	if linkID != "" {
		//unBindSwitch := myUserHelp.G_UserButton.GetUnbind(linkID)
		operatorId = myUserHelp.GetMemberOperatorId(linkID)
		businessId = myUserHelp.GetMemberBusinessId(linkID)
		canbind := myUserHelp.CanBindParent(linkID)

		//绑定
		myUserHelp.AddAreaTotalInviteCounts(linkID, 1)
		myUserHelp.AddMinInviteCounts(linkID, 1)

		if !canbind {
			myUserHelp.AddTotalDisbindCounts(linkID, 1)
			myUserHelp.AddMinDisbindCounts(linkID, 1)
		}

		if !canbind {
			unbindParentId = linkID
			linkID = ""
		}
	}
	if businessId == "" {
		businessId = "0"
	}

	if operatorId == "" || operatorId == "0" {
		operatorId = myConfig.Def_Channel
	}
	var (
		realName = ""
		currency = ""
	)
	if r, exists := extendParams["RealName"]; exists {
		realName = r.(string)
	}
	if c, exists := extendParams["Currency"]; exists {
		currency = c.(string)
	}

	var strRemake string = ""
	if linkID != "" {
		ParentRemake := myUserHelp.GetMemberRemake(linkID)
		if strings.Contains(ParentRemake, "team:") {
			strRemake = ParentRemake
		}
	}

	m := myUserHelp.TblMemberBase{
		Uid:         uid,
		Pid:         helper.GenId(),
		Username:    username,
		Phone:       phone,
		Email:       email,
		Password:    password,
		CreatedIp:   ip,
		CreatedAt:   createdAt,
		LastLoginAt: createdAt,
		Tester:      1,
		State:       1,
		PayPassword: "0",
		Prefix:      prefix,
		OperatorId:  operatorId,
		BusinessId:  businessId,
		InviteCode:  "0",
		LastLoginIp: "0",
		RealName:    realName,
		Currency:    currency,
		Remake:      strRemake,
	}

	BaseInsertSql, _, _ := dialect.Insert("tbl_member_base").Rows(&m).ToSQL()

	b := myUserHelp.TblMemberBalance{
		Prefix:            prefix,
		Uid:               uid,
		Brl:               0,
		LockAmount:        0,
		UnlockAmount:      0,
		AgencyAmount:      0,
		DepositLockAmount: 0,
		AgencyLockAmount:  0,
	}
	BalanceInsertSql, _, _ := dialect.Insert("tbl_member_balance").Rows(&b).ToSQL()

	errReg := CreateUserTable(uid, BaseInsertSql, BalanceInsertSql, linkID, unbindParentId, operatorId, ip, username)
	if errReg != nil {
		helper.SqlSelectErrLog("reg error,%s", errReg.Error())
		return "", errors.New(helper.UsernameExist)
	}

	id, err := session.Set([]byte(m.Uid), m.Uid)
	if err != nil {
		helper.SqlSelectErrLog("set token error,%s", err.Error())
		return "", errors.New(helper.SessionErr)
	}

	if phone != "" {
		err = meta.MerchantRedis.SAdd(ctx, "phoneExist", phone).Err()
		if err != nil {
			helper.SqlSelectErrLog("add redis key %s error,%s", "phoneExist", err.Error())
		}
	}
	if email != "" {
		err = meta.MerchantRedis.SAdd(ctx, "emailExist", email).Err()
		if err != nil {
			helper.SqlSelectErrLog("add redis key %s error,%s", "emailExist", err.Error())
		}
	}
	if username != "" {
		usernamePrefix := username + prefix
		err = meta.MerchantRedis.SAdd(ctx, "usernameExist", usernamePrefix).Err()
		if err != nil {
			helper.SqlSelectErrLog("add redis key %s error,%s", "usernameExist", err.Error())
		}
	}

	if linkID != "" && linkID != "0" {

		//处理邀请人数
		_, errExec := GetMasterDBInstance().Exec("CALL tbl_report_user_business_inviteNum_update(?,?,?)", uid, 1, time.Now().Unix())
		if errExec != nil {
			pushLog(fmt.Errorf("%s,[tbl_report_user_business_inviteNum_update]", errExec.Error()), helper.DBErr)
		}
	}

	return id, nil
}

// 检测会员账号是否已存在
func MemberExist(username string) bool {

	key := "member:" + username
	exists := meta.MerchantRedis.Exists(ctx, key).Val()
	if exists == 0 {
		return false
	}

	return true
}

func MemberBindCheck(ex g.Ex) bool {

	var id string

	t := dialect.From("tbl_member_base")
	query, _, _ := t.Select("uid").Where(ex).Limit(1).ToSQL()
	err := meta.MerchantDB.Get(&id, query)
	if err == sql.ErrNoRows {
		helper.InfoLog("MemberBindCheck:%s", query)
		return false
	}

	return true
}

func MemberNav() ([]byte, error) {

	res, err := meta.MerchantRedis.Get(ctx, "nav").Bytes()
	if err != nil {
		return res, pushLog(err, helper.RedisErr)
	}

	return res, nil
}

// 会员忘记密码
func MemberForgetPwd(pwd, phone, email, ip, sid, code, ts, prefix string) error {
	AccountName := phone
	if AccountName == "" {
		AccountName = email
	}

	uid, ret := myUserHelp.GetMemberIdByAccountName(phone, prefix)
	if !ret {
		return errors.New(helper.UserNotExist)
	}

	var err error
	if phone != "" {
		err = CheckSmsCaptcha(ip, sid, "55"+phone, code)
		if err != nil {
			return err
		}
	}
	if email != "" {
		err = CheckEmailCaptcha(ip, sid, email, code)
		if err != nil {
			return err
		}
	}
	//密码加密效验,上线时候放开
	//pwd = fmt.Sprintf("%d", MurmurHash(pwd,  myUserHelp.GetMemberCreateAt(uid)))
	myUserHelp.SetMemberLoginPsw(uid, pwd)

	key := fmt.Sprintf("MPE:%s", myUserHelp.GetMemberName(uid))
	err = meta.MerchantRedis.Unlink(ctx, key).Err()
	if err != nil {
		return pushLog(err, "redis")
	}

	return nil
}

// shortURLGen uri 原始url,返回短url
func shortURLGen(uri string) (string, error) {

	for i := 0; i < 100; i++ {

		shortCode := shortUrlGenCode()
		key := fmt.Sprintf("shortcode:%s", shortCode)

		err := meta.MerchantRedis.SetNX(ctx, key, uri, 0).Err()
		if err != nil {
			continue
		}

		return shortCode, nil
	}
	return "", errors.New(helper.RedisErr)
}

// shortUrlGenCode 传入ID生成短码
func shortUrlGenCode() string {

	hd := hashids.NewData()
	hd.Salt = helper.GenId()
	hd.MinLength = 6
	h, _ := hashids.NewWithData(hd)
	shortCode, _ := h.EncodeInt64([]int64{time.Now().UnixMilli()})
	return shortCode
}

// 更新用户密码
func MemberPasswordUpdate(old, password string, fctx *fasthttp.RequestCtx) error {

	uid := GetUidFromToken(fctx)
	if uid == "" {

		return errors.New(helper.AccessTokenExpires)
	}
	myUserHelp.LoadUserToRedis(uid)
	Password := myUserHelp.GetMemberLoginPsw(uid)
	//密码加密效验,上线时候放开
	//password = fmt.Sprintf("%d", MurmurHash(password,  myUserHelp.GetMemberCreateAt(uid)))
	if password == Password {
		return errors.New(helper.PasswordConsistent)
	}
	//old = fmt.Sprintf("%d", MurmurHash(old, myUserHelp.GetMemberCreateAt(uid)))
	/*
		if old != Password {
			return errors.New(helper.OldPasswordErr)
		}
	*/

	myUserHelp.SetMemberLoginPsw(uid, password)
	return nil
}

func MemberPayPasswordUpdate(updateType, ty int, sid, code, confirmPassword, password, ts, old, phone string, fctx *fasthttp.RequestCtx) error {

	uid := GetUidFromToken(fctx)
	if uid == "" {

		return errors.New(helper.AccessTokenExpires)
	}

	myUserHelp.LoadUserToRedis(uid)

	if updateType == 1 {
		if confirmPassword != password {
			return errors.New(helper.PasswordInconsistent)
		}
		myUserHelp.SetMemberPayPsw(uid, password)
	} else if updateType == 2 {
		/*
			if old != myUserHelp.GetMemberPayPsw(uid) {
				return errors.New(helper.OldPasswordErr)
			}
		*/
		if confirmPassword != password {
			return errors.New(helper.PasswordInconsistent)
		}
		myUserHelp.SetMemberPayPsw(uid, password)
	} else {
		ip := helper.FromRequest(fctx)
		// 手机修改
		if ty == 1 {
			if phone != myUserHelp.GetMemberPhone(uid) {
				return errors.New(helper.PhoneNumberErr)
			}
			if !helper.CtypeDigit(code) {
				return errors.New(helper.PhoneVerificationErr)
			}
			CheckSms := CheckSmsCaptcha(ip, sid, "55"+phone, code)
			if CheckSms != nil {
				return CheckSms
			}
		}
		if ty == 2 {
			if !helper.CtypeDigit(sid) {
				return errors.New(helper.ParamErr)
			}
			if !helper.CtypeDigit(ts) {
				return errors.New(helper.ParamErr)
			}
			if !helper.CtypeDigit(code) {
				return errors.New(helper.ParamErr)
			}
			errCheckEmail := CheckEmailCaptcha(ip, sid, myUserHelp.GetMemberEmail(uid), code)
			if errCheckEmail != nil {
				return errCheckEmail
			}
		}

		myUserHelp.SetMemberPayPsw(uid, password)
	}

	return nil
}

// 更新用户信息
func MemberUpdateEmail(email, ts string, fctx *fasthttp.RequestCtx) error {

	ex := g.Ex{
		"email": email,
	}
	if MemberBindCheck(ex) {
		return errors.New(helper.EmailExist)
	}

	uid := GetUidFromToken(fctx)
	if uid == "" {

		return errors.New(helper.AccessTokenExpires)
	}

	myUserHelp.LoadUserToRedis(uid)

	//会员绑定邮箱后,不允许再修改邮箱
	/*
		if myUserHelp.GetMemberEmail(uid) != "" {
			return errors.New(helper.EmailBindAlreadyErr)
		}
	*/

	myUserHelp.SetMemberEmail(uid, email)
	return nil
}

// 更新用户手机号
func MemberUpdatePhone(ts, phone string, fctx *fasthttp.RequestCtx) error {

	ex := g.Ex{
		"phone": phone,
	}
	if MemberBindCheck(ex) {
		return errors.New(helper.PhoneExist)
	}

	uid := GetUidFromToken(fctx)
	if uid == "" {

		return errors.New(helper.AccessTokenExpires)
	}

	myUserHelp.LoadUserToRedis(uid)

	//会员绑定手机号后，不允许再修改手机号
	if myUserHelp.GetMemberPhone(uid) != "" {
		return errors.New(helper.PhoneBindAlreadyErr)
	}

	myUserHelp.SetMemberPhone(uid, phone)
	return nil
}

func MemberUpdateInfo(fctx *fasthttp.RequestCtx, phone, email, username string) error {

	uid := GetUidFromToken(fctx)
	if uid == "" {

		return errors.New(helper.AccessTokenExpires)
	}
	myUserHelp.LoadUserToRedis(uid)

	//record := g.Record{}
	//if phone != "" {
	//	ex := g.Ex{
	//		"phone": phone,
	//	}
	//	if MemberBindCheck(ex) {
	//		return errors.New(helper.PhoneExist)
	//	} else {
	//		myUserHelp.SetMemberPhone(uid, phone)
	//	}
	//}
	if email != "" {
		ex := g.Ex{
			"email": email,
		}
		if MemberBindCheck(ex) {
			return errors.New(helper.EmailExist)
		} else {
			myUserHelp.SetMemberEmail(uid, email)
		}
	}

	if username != "" {
		myUserHelp.SetMemberName(uid, username)
	} else {
		return errors.New(helper.UsernameErr)
	}

	return nil
}

func TurntableSwitch() bool {
	cfgVal := myConfig.GetGameCfgInt(myConfig.CfgTurntableSwitch)

	if cfgVal == 1 {
		return true
	} else {
		return false
	}
}

func GetMemberByUsernameOrPhone(account string) (*myUserHelp.TblMemberBase, error) {
	t := dialect.From("tbl_member_base")
	ex := g.ExOr{
		"phone":    account,
		"username": account,
	}
	query, _, _ := t.Where(ex).Limit(1).ToSQL()
	res := myUserHelp.TblMemberBase{}
	err := meta.MerchantDB.Get(&res, query)
	if err == sql.ErrNoRows {
		return &res, errors.New(helper.UsernameErr)
	}
	return &res, nil
}

func MemberPayPasswordVerification(payPassword string, fctx *fasthttp.RequestCtx) error {

	uid := GetUidFromToken(fctx)
	if uid == "" {
		return errors.New(helper.AccessTokenExpires)
	}

	PayPassword := myUserHelp.GetMemberPayPsw(uid)
	if payPassword != PayPassword {
		helper.SqlSelectErrLog("payPassword err, input:%s, mysql:%s, uid:%s", payPassword, PayPassword, uid)
		return errors.New(helper.WithdrawPwdMismatch)
	}
	return nil
}

type TblMemberVerify struct {
	Uid      string `db:"uid" json:"uid"`
	RealName string `db:"real_name" json:"real_name"` // 用户名
	Cpf      string `db:"cpf" json:"cpf"`             // 密码
}

func GetMemberVerifyInfo(uid string) (TblMemberVerify, error) {
	var data TblMemberVerify
	query, _, _ := dialect.From("tbl_member_verify").Select("*").Where(g.Ex{"uid": uid}).ToSQL()

	err := meta.MerchantDB.Get(&data, query)
	if err != nil && err != sql.ErrNoRows {
		helper.SqlSelectErrLog("%s--%s", query, err.Error())

	}
	return data, nil
}

func MemberVerifyInfo(data TblMemberVerify) error {
	mb, err := GetMemberVerifyInfo(data.Uid)
	if err != nil {
		helper.SqlSelectErrLog("query err:%s", err)
	}
	if mb.Uid != "" {
		query, _, _ := dialect.Update("tbl_member_verify").Set(data).Where(g.Ex{"uid": data.Uid}).ToSQL()
		_, err = meta.MerchantDB.Exec(query)
		if err != nil {
			return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
		}
		return nil
	} else {
		verifyInfo := TblMemberVerify{
			Uid:      data.Uid,
			Cpf:      data.Cpf,
			RealName: data.RealName,
		}
		query, _, _ := dialect.Insert("tbl_member_verify").Rows(verifyInfo).ToSQL()
		_, err = meta.MerchantDB.Exec(query)
		if err != nil {
			return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
		}
		return nil
	}
}

type TblDepositPixel struct {
	Id        string `json:"id" db:"id"`
	Oid       string `json:"oid" db:"oid"`
	Uid       string `json:"uid" db:"uid"`
	Amount    string `json:"amount" db:"amount"`
	CreatedAt string `json:"created_at" db:"created_at"`
	IsFirst   int    `json:"is_first" db:"is_first"`
}

func GetMemberDepositInfo(uid string) ([]TblDepositPixel, error) {
	var data []TblDepositPixel
	ex := g.Ex{"uid": uid}
	query, _, _ := dialect.From("tbl_deposit_pixel").Select(colsDepositPixel...).Where(ex).ToSQL()
	err := meta.MerchantDB.Select(&data, query)
	if err != nil && err != sql.ErrNoRows {
		helper.SqlSelectErrLog("%s--%s", query, err.Error())

	}

	update, _, _ := dialect.Delete("tbl_deposit_pixel").Where(ex).ToSQL()
	_, err = meta.MerchantDB.Exec(update)
	if err != nil {
		helper.SqlSelectErrLog("%s--%s", query, err.Error())
	}
	return data, nil
}
